#if (FEATURE_MODE == 0) && defined E_UNIT

/**
 @file sys_usw_eunit.c

 @date 2019-10-14

 @version v1.0

*/

/****************************************************************
 *
 * Header Files
 *
 ***************************************************************/
#include "ctc_error.h"
#include "drv_api.h"
#include "usw/include/drv_common.h"

#include "sys_usw_mchip.h"
#include "sys_usw_eunit.h"
#include "sys_usw_common.h"


sys_usw_eunit_isr_t g_eunit_isr[SYS_EUNIT_ISR_MAX] = {NULL};

#define EUNIT_HEART_TIMEOUT 300 /* 5min */
#define SYS_USW_EUNIT_MAX_PC_NUM 4
sys_usw_eunit_master_t* p_usw_eunit_master[CTC_MAX_LOCAL_CHIP_NUM_PP] = {NULL};

/*extern int32 sys_emsg_init(uint8 lchip);
extern int32 sys_emsg_deinit(uint8 lchip);*/
#define SYS_EUNIT_LOCK(lchip)    if (p_usw_eunit_master[lchip]->mutex) {sal_mutex_lock(p_usw_eunit_master[lchip]->mutex);}
#define SYS_EUNIT_UNLOCK(lchip)  if (p_usw_eunit_master[lchip]->mutex) {sal_mutex_unlock(p_usw_eunit_master[lchip]->mutex);}

#define SYS_EUNIT_INIT_CHECK(lchip)  \
    {                                \
        LCHIP_CHECK(lchip);          \
        if (!p_usw_eunit_master[lchip]) { \
            return CTC_E_NOT_INIT; } \
    }

STATIC int32
_sys_usw_eunit_error_isr_func(uint8 lchip, uint8 isr_type, void* p_data)
{
    sys_usw_eunit_isr_data_t* isr_data = (sys_usw_eunit_isr_data_t*)p_data;
    if (NULL == isr_data)
    {
        return CTC_E_INVALID_PARAM;
    }
    /*DEBUG*/
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_EXPORT, "Eunit runing error. unitId:%d isrID:%d\n ",isr_data->unit, isr_data->irq_id);
    return CTC_E_NONE;
}

int32
sys_usw_eunit_reset(uint8 lchip, uint8 unit, ctc_eunit_install_t* p_eunit)
{
    int32 ret = CTC_E_NONE;
#if (SDK_WORK_PLATFORM == 0) || defined (EUNIT_SIM)
    if (lchip != SYS_PP_BASE(lchip))
    {
        return CTC_E_NONE;
    }
    SYS_EUNIT_INIT_CHECK(lchip);
    CTC_MAX_VALUE_CHECK(unit, MCHIP_CAP(SYS_CAP_EUNIT_NUM) - 1);
    SYS_EUNIT_LOCK(lchip);
    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->reset)
    {
        /*reset*/
        ret = MCHIP_EUNIT(lchip)->reset(lchip, unit, p_eunit);
        SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "unitId:%d reset times:%u! file:%s\n", unit, p_usw_eunit_master[lchip]->reset_times[unit], (p_eunit&&p_eunit->bin_file) ? p_eunit->bin_file : "");
    }
    SYS_EUNIT_UNLOCK(lchip);
#endif
    return ret;
}

int32
sys_usw_eunit_isr_handler(uint8 lchip, uint32 intr, void* p_data)
{
    int32 ret = CTC_E_NONE;
#if (SDK_WORK_PLATFORM == 0) || defined (EUNIT_SIM)
    SYS_EUNIT_INIT_CHECK(lchip);
    SYS_EUNIT_LOCK(lchip);
    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->isr_handler)
    {
        ret = MCHIP_EUNIT(lchip)->isr_handler(lchip, intr, p_data);
    }
    SYS_EUNIT_UNLOCK(lchip);
#endif
    return ret;
}


int32
sys_usw_eunit_regitser_isr(uint8 lchip, uint8 isr_type, sys_usw_eunit_isr_t isr)
{
    if (isr_type >= SYS_EUNIT_ISR_MAX)
    {
        return CTC_E_INVALID_PARAM;
    }
    g_eunit_isr[isr_type] = isr;
    return CTC_E_NONE;
}

int32
sys_usw_eunit_set_cfg(uint8 lchip, uint8 type, void* p_cfg)
{
    int32 ret = CTC_E_NONE;
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
#if (SDK_WORK_PLATFORM == 0) || defined (EUNIT_SIM)
    SYS_EUNIT_INIT_CHECK(lchip);
    SYS_EUNIT_LOCK(lchip);
    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->set_cfg)
    {
        ret = MCHIP_EUNIT(lchip)->set_cfg(lchip, type, p_cfg);
    }
    SYS_EUNIT_UNLOCK(lchip);
#else
    ret = CTC_E_NONE;
#endif
    return ret;
}

int32
sys_usw_eunit_get_cfg(uint8 lchip, uint8 type, void* p_cfg)
{
    int32 ret = CTC_E_NONE;
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    LCHIP_CHECK(lchip);
	lchip = SYS_PP_BASE(lchip);
#if (SDK_WORK_PLATFORM == 0) || defined (EUNIT_SIM)
    SYS_EUNIT_INIT_CHECK(lchip);

    SYS_EUNIT_LOCK(lchip);
    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->get_cfg)
    {
        ret = MCHIP_EUNIT(lchip)->get_cfg(lchip, type, p_cfg);
    }
    SYS_EUNIT_UNLOCK(lchip);
#else
    ret = CTC_E_NONE;
#endif
    return ret;
}

/*lock_type refer to drv_eunit_lock_type_t*/
int32
sys_usw_eunit_lock_cb(uint8 lchip, uint8 lock_type, uint8 status)
{

    SYS_EUNIT_INIT_CHECK(lchip);
    switch(lock_type)
    {
        case DRV_EUNIT_LOCK_FIBACC:
            if (status)
            {
                CTC_ERROR_RETURN(sys_usw_eunit_hw_lock(lchip, p_usw_eunit_master[lchip]->eunit_la_id, DRV_EUNIT_LOCK_FIBACC));
            }
            else
            {
                CTC_ERROR_RETURN(sys_usw_eunit_hw_unlock(lchip, p_usw_eunit_master[lchip]->eunit_la_id, DRV_EUNIT_LOCK_FIBACC));
            }
            break;
        default:
            return CTC_E_INVALID_PARAM;
    }
    return CTC_E_NONE;
}

int32
sys_usw_eunit_hw_lock(uint8 lchip, uint8 eunit_id, uint8 lock_id)
{
    int32 ret = CTC_E_NONE;
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
#if (SDK_WORK_PLATFORM == 0) || defined (EUNIT_SIM)
    SYS_EUNIT_INIT_CHECK(lchip);
    SYS_EUNIT_LOCK(lchip);
    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->hw_lock)
    {
        ret = MCHIP_EUNIT(lchip)->hw_lock(lchip, eunit_id, lock_id);
    }
    SYS_EUNIT_UNLOCK(lchip);
#endif
    return ret;
}

int32
sys_usw_eunit_hw_unlock(uint8 lchip, uint8 eunit_id, uint8 lock_id)
{
    int32 ret = CTC_E_NONE;
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
#if (SDK_WORK_PLATFORM == 0) || defined (EUNIT_SIM)
    SYS_EUNIT_INIT_CHECK(lchip);
    SYS_EUNIT_LOCK(lchip);
    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->hw_unlock)
    {
        ret = MCHIP_EUNIT(lchip)->hw_unlock(lchip, eunit_id, lock_id);
    }
    SYS_EUNIT_UNLOCK(lchip);
#endif
    return ret;
}

int32
sys_usw_eunit_get_hw_lock(uint8 lchip, uint8 type, uint8* p_eunit_id, uint8* p_lock_id)
{
    int32 ret = CTC_E_NONE;
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
#if (SDK_WORK_PLATFORM == 0) || defined (EUNIT_SIM)
    SYS_EUNIT_INIT_CHECK(lchip);
    SYS_EUNIT_LOCK(lchip);
    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->hw_unlock)
    {
        ret = MCHIP_EUNIT(lchip)->get_hw_lock(lchip, type, p_eunit_id, p_lock_id);
    }
    SYS_EUNIT_UNLOCK(lchip);
#endif
    return ret;
}


int32
sys_usw_eunit_show_pclog(uint8 lchip, uint8 eunit_id)
{
#if (SDK_WORK_PLATFORM == 0) || defined (EUNIT_SIM)
    uint64 pc_arr[SYS_USW_EUNIT_MAX_PC_NUM] = {0};
    uint8 index = 0;
    uint8 num = SYS_USW_EUNIT_MAX_PC_NUM;
#endif
    int32 ret = CTC_E_NONE;
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    LCHIP_CHECK(lchip);
	lchip = SYS_PP_BASE(lchip);
    CTC_MAX_VALUE_CHECK(eunit_id, MCHIP_CAP(SYS_CAP_EUNIT_NUM) - 1);
#if (SDK_WORK_PLATFORM == 0) || defined (EUNIT_SIM)
    SYS_EUNIT_INIT_CHECK(lchip);
    SYS_EUNIT_LOCK(lchip);
    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->get_pclog)
    {
        ret = MCHIP_EUNIT(lchip)->get_pclog(lchip, eunit_id, pc_arr, &num);
    }
    SYS_EUNIT_UNLOCK(lchip);
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"---------------------------------------------------------------------------------\n");
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"Eunit ID: %u Pclog\n",eunit_id);
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"---------------------------------------------------------------------------------\n");

    for(index = 0; index < num; index++)
    {
        SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"Pc%u: 0x%010"PRIx64"\n",index, pc_arr[index]);
    }

#endif
    return ret;
}

int32
sys_usw_euint_tbl_rw(uint8 lchip, uint8 eunit_id, uint32 tbl_id, uint32 tbl_idx, uint32 opbmp, uint8 data, uint8 mask, uint8 op_type)
{
    int32 ret = CTC_E_NONE;
#if (SDK_WORK_PLATFORM == 0) || defined (EUNIT_SIM)
    uint32 tbl_addr;
    uint32 index;
    sys_usw_eunit_tbl_rw_t tbl_rw;
#endif

    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    LCHIP_CHECK(lchip);
	lchip = SYS_PP_BASE(lchip);

#if (SDK_WORK_PLATFORM == 0) || defined (EUNIT_SIM)

    SYS_EUNIT_INIT_CHECK(lchip);
    CTC_MAX_VALUE_CHECK(eunit_id, MCHIP_CAP(SYS_CAP_EUNIT_NUM) - 1);
    CTC_MAX_VALUE_CHECK(op_type, SYS_USW_EUNIT_TBL_RW_TYPE_MAX - 1);
    if (SYS_USW_EUNIT_TBL_RW_TYPE_WITH_MASK == op_type)
    {
        CTC_MAX_VALUE_CHECK(DRV_TABLE_ENTRY_SIZE(lchip, tbl_id)/sizeof(uint32), 32);
    }
    else
    {
        CTC_MAX_VALUE_CHECK(DRV_TABLE_ENTRY_SIZE(lchip, tbl_id)/sizeof(uint32), 64);
    }

    if (tbl_id >= (MaxTblId_t))
    {
        return DRV_E_INVALID_TBL;
    }

    if (0 == DRV_TABLE_MAX_INDEX(lchip, tbl_id) || tbl_idx >= DRV_TABLE_MAX_INDEX(lchip, tbl_id))
    {
        return CTC_E_NOT_EXIST;
    }


    CTC_ERROR_RETURN(drv_get_table_property(lchip, DRV_TABLE_PROP_HW_ADDR, tbl_id, tbl_idx, &tbl_addr));
    sal_memset(&tbl_rw, 0, sizeof(sys_usw_eunit_tbl_rw_t));
    tbl_rw.addr = tbl_addr;

    tbl_rw.len = DRV_TABLE_ENTRY_SIZE(lchip, tbl_id)/sizeof(uint32);

    tbl_rw.oper_bmp = opbmp & 0xfff;

    if (SYS_USW_EUNIT_TBL_RW_TYPE_WRITE == op_type)
    {
        sal_memset(tbl_rw.data, data, DRV_TABLE_ENTRY_SIZE(lchip, tbl_id));
    }
    else if(SYS_USW_EUNIT_TBL_RW_TYPE_WITH_MASK == op_type)
    {
        sal_memset(tbl_rw.data, data, DRV_TABLE_ENTRY_SIZE(lchip, tbl_id));
        sal_memset(tbl_rw.data+tbl_rw.len, mask, DRV_TABLE_ENTRY_SIZE(lchip, tbl_id));
    }

    SYS_EUNIT_LOCK(lchip);
    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->tbl_rw)
    {
        ret = MCHIP_EUNIT(lchip)->tbl_rw(lchip, eunit_id, (void*)&tbl_rw, op_type);
    }
    SYS_EUNIT_UNLOCK(lchip);
    if (CTC_E_NONE == ret && SYS_USW_EUNIT_TBL_RW_TYPE_READ == op_type)
    {
        /*dump*/
       SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"---------------------------- read table results----------------------------------\n");
       SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"Eunit ID: %u\n",eunit_id);
       SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"---------------------------------------------------------------------------------\n");
       SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"table id:%u \t index:%u\n",tbl_id, tbl_idx);
       SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"---------------------------------------------------------------------------------\n");
       SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"data dump:\n");
       for(index = 0; index < tbl_rw.len ;index++)
       {
           SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"0x%08x: 0x%08x\n", tbl_rw.addr + index*4, tbl_rw.data[index]);
       }
    }
#endif
    return ret;

}

int32
sys_usw_eunit_show_dma_status(uint8 lchip, uint8 eunit_id)
{
    int32 ret = CTC_E_NONE;
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    LCHIP_CHECK(lchip);
	lchip = SYS_PP_BASE(lchip);

#if (SDK_WORK_PLATFORM == 0) || defined (EUNIT_SIM)
    SYS_EUNIT_INIT_CHECK(lchip);
    SYS_EUNIT_LOCK(lchip);
    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->show_dma_status)
    {
        ret = MCHIP_EUNIT(lchip)->show_dma_status(lchip, eunit_id);
    }
    SYS_EUNIT_UNLOCK(lchip);
#endif
        return ret;
}

int32
sys_usw_eunit_show_dma_desc(uint8 lchip, uint8 eunit_id, uint8 chan_id, uint32 start_idx, uint32 end_idx)
{
    int32 ret = CTC_E_NONE;
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    LCHIP_CHECK(lchip);
	lchip = SYS_PP_BASE(lchip);

#if (SDK_WORK_PLATFORM == 0) || defined (EUNIT_SIM)
    SYS_EUNIT_INIT_CHECK(lchip);
    SYS_EUNIT_LOCK(lchip);
    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->show_dma_desc)
    {
        ret = MCHIP_EUNIT(lchip)->show_dma_desc(lchip, eunit_id, chan_id, start_idx, end_idx);
    }
    SYS_EUNIT_UNLOCK(lchip);
#endif
    return ret;

}


int32
sys_usw_eunit_show_mem(uint8 lchip, uint32 addr, uint32 len)
{
    int32 ret = CTC_E_NONE;
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    LCHIP_CHECK(lchip);
	lchip = SYS_PP_BASE(lchip);

#if (SDK_WORK_PLATFORM == 0) || defined (EUNIT_SIM)
    SYS_EUNIT_INIT_CHECK(lchip);
    SYS_EUNIT_LOCK(lchip);
    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->show_mem)
    {
        ret = MCHIP_EUNIT(lchip)->show_mem(lchip, addr, len);
    }
    SYS_EUNIT_UNLOCK(lchip);
#endif
    return ret;

}

int32
sys_usw_eunit_show_io_log(uint8 lchip, uint8 eunit_id, uint8 clear_en)
{
    int32 ret = CTC_E_NONE;
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    LCHIP_CHECK(lchip);
	lchip = SYS_PP_BASE(lchip);

    CTC_MAX_VALUE_CHECK(eunit_id, MCHIP_CAP(SYS_CAP_EUNIT_NUM) - 1);
#if (SDK_WORK_PLATFORM == 0) || defined (EUNIT_SIM)
    SYS_EUNIT_INIT_CHECK(lchip);
    SYS_EUNIT_LOCK(lchip);
    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->show_io_log)
    {
        ret = MCHIP_EUNIT(lchip)->show_io_log(lchip, eunit_id, clear_en);
    }
    SYS_EUNIT_UNLOCK(lchip);
#endif
    return ret;

}

int32
sys_usw_eunit_show_dbg_info(uint8 lchip, uint8 eunit_id)
{
    int32 ret = CTC_E_NONE;
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    LCHIP_CHECK(lchip);
    lchip = SYS_PP_BASE(lchip);

    SYS_EUNIT_INIT_CHECK(lchip);
    SYS_EUNIT_LOCK(lchip);
    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->show_dbg_info)
    {
        ret = MCHIP_EUNIT(lchip)->show_dbg_info(lchip, eunit_id);
    }
    SYS_EUNIT_UNLOCK(lchip);

    return ret;
}

int32
sys_usw_eunit_show_dma_stats(uint8 lchip, uint8 eunit_id)
{
    int32 ret = CTC_E_NONE;
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    LCHIP_CHECK(lchip);
	lchip = SYS_PP_BASE(lchip);

#if (SDK_WORK_PLATFORM == 0) || defined (EUNIT_SIM)
    SYS_EUNIT_INIT_CHECK(lchip);
    SYS_EUNIT_LOCK(lchip);
    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->show_dma_stats)
    {
        ret = MCHIP_EUNIT(lchip)->show_dma_stats(lchip, eunit_id);
    }
    SYS_EUNIT_UNLOCK(lchip);
#endif
    return ret;
}

int32
sys_usw_eunit_clear_dma_stats(uint8 lchip, uint8 eunit_id)
{
    int32 ret = CTC_E_NONE;
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    LCHIP_CHECK(lchip);
	lchip = SYS_PP_BASE(lchip);

#if (SDK_WORK_PLATFORM == 0) || defined (EUNIT_SIM)
    SYS_EUNIT_INIT_CHECK(lchip);
    SYS_EUNIT_LOCK(lchip);
    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->clear_dma_stats)
    {
        ret = MCHIP_EUNIT(lchip)->clear_dma_stats(lchip, eunit_id);
    }
    SYS_EUNIT_UNLOCK(lchip);
#endif
    return ret;
}

/*
run_status : SYS_EUNIT_RUN_STATUS_XXX
*/
int32
sys_usw_eunit_set_run_status(uint8 lchip, uint8 eunit_id, uint32 run_status)
{
    int32 ret = CTC_E_NONE;
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    LCHIP_CHECK(lchip);
	lchip = SYS_PP_BASE(lchip);

#if (SDK_WORK_PLATFORM == 0) || defined (EUNIT_SIM)
    SYS_EUNIT_INIT_CHECK(lchip);
    SYS_EUNIT_LOCK(lchip);
    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->set_run_status)
    {
        ret = MCHIP_EUNIT(lchip)->set_run_status(lchip, eunit_id, run_status);
    }
    SYS_EUNIT_UNLOCK(lchip);
#endif
    return ret;
}



int32
sys_usw_eunit_get_unit_id(uint8 lchip, uint8 type, uint8* uint)
{
    int32 ret = CTC_E_NONE;
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
#if (SDK_WORK_PLATFORM == 0) || defined (EUNIT_SIM)
    SYS_EUNIT_INIT_CHECK(lchip);

    SYS_EUNIT_LOCK(lchip);
    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->set_cfg)
    {
        ret = MCHIP_EUNIT(lchip)->get_unit(lchip, type, uint);
    }
    SYS_EUNIT_UNLOCK(lchip);
#endif
    return ret;
}

int32
sys_usw_eunit_show_status(uint8 lchip, uint8 level, void* p_params)
{
    int32 ret = CTC_E_NONE;
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    LCHIP_CHECK(lchip);
	lchip = SYS_PP_BASE(lchip);

#if (SDK_WORK_PLATFORM == 0) || defined (EUNIT_SIM)
    SYS_EUNIT_INIT_CHECK(lchip);

    SYS_EUNIT_LOCK(lchip);
    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->show_status)
    {
        ret = MCHIP_EUNIT(lchip)->show_status(lchip, level, p_params);
    }
    SYS_EUNIT_UNLOCK(lchip);
#endif
    return ret;
}

int32
sys_usw_eunit_get_cpu_reason_info(uint8 lchip, uint8 eunit_id, sys_eunit_cpu_reason_info_t* p_info)
{
    SYS_EUNIT_INIT_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_info);
    CTC_MAX_VALUE_CHECK(eunit_id, MCHIP_CAP(SYS_CAP_EUNIT_NUM) - 1);

    if (!DRV_FROM_AT(lchip))
    {
        return CTC_E_NOT_SUPPORT;
    }

    p_info->reason_group = MCHIP_CAP(SYS_CAP_CPU_REASON_GRP_BASE_EUNIT) + eunit_id / 2;
    p_info->queue_id = (eunit_id & 0x1) * 2;
    p_info->queue_num = 2;
    return CTC_E_NONE;
}

int32
sys_usw_eunit_show_cpu_reason_info(uint8 lchip, uint8 eunit_id)
{
    sys_eunit_cpu_reason_info_t reason_info;
    SYS_EUNIT_INIT_CHECK(lchip);
    CTC_MAX_VALUE_CHECK(eunit_id, MCHIP_CAP(SYS_CAP_EUNIT_NUM) - 1);

    CTC_ERROR_RETURN(sys_usw_eunit_get_cpu_reason_info(lchip, eunit_id, &reason_info));
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "eunit_id: %d CPU Reason Info:\n", eunit_id);
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-20s: %u\n", "reason-group", reason_info.reason_group);
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-20s: %u\n", "queue-id", reason_info.queue_id);
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-20s: %u\n", "queue-num", reason_info.queue_num);
    return CTC_E_NONE;
}

int32
sys_usw_eunit_hw_reset(uint8 lchip, void* data)
{
    uint32 hw_reset_en = *((uint32*)data);
    sys_usw_eunit_set_cfg(lchip, SYS_EUNIT_CFG_HW_RESET, &hw_reset_en);

    return CTC_E_NONE;
}

int32
sys_usw_eunit_get_usr_config_cmd(uint8 lchip, void* p_value)
{
    CTC_PTR_VALID_CHECK(p_value);
    
    return sys_usw_eunit_get_cfg(lchip, SYS_EUNIT_CFG_USER_CFG, p_value);
}
int32
sys_usw_eunit_set_usr_config_cmd(uint8 lchip, void* p_value)
{
    CTC_PTR_VALID_CHECK(p_value);
    
    return sys_usw_eunit_set_cfg(lchip, SYS_EUNIT_CFG_USER_CFG, p_value);
}
int32
sys_usw_eunit_get_app_alive_cnt(uint8 lchip, void* p_value)
{
    CTC_PTR_VALID_CHECK(p_value);
    
    return sys_usw_eunit_get_cfg(lchip, SYS_EUNIT_CFG_APP_STATUS, p_value);
}



int32
sys_usw_eunit_show_version(uint8 lchip, uint8 eunit_id)
{
    int32 ret = CTC_E_NONE;
    SYS_EUNIT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    LCHIP_CHECK(lchip);
	lchip = SYS_PP_BASE(lchip);

#if (SDK_WORK_PLATFORM == 0) || defined (EUNIT_SIM)
    SYS_EUNIT_INIT_CHECK(lchip);
    SYS_EUNIT_LOCK(lchip);
    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->show_version)
    {
        ret = MCHIP_EUNIT(lchip)->show_version(lchip, eunit_id);
    }
    SYS_EUNIT_UNLOCK(lchip);
#endif
        return ret;
}

int32
sys_usw_eunit_deinit(uint8 lchip)
{
    LCHIP_CHECK(lchip);
    if (!DRV_FROM_TMM(lchip))
    {
        return CTC_E_NONE;
    }
    if (NULL == p_usw_eunit_master[lchip])
    {
        return CTC_E_NONE;
    }
    sys_usw_eunit_regitser_isr(lchip, SYS_EUNIT_ISR_ERROR, NULL);

    if (p_usw_eunit_master[lchip]->mutex)
    {
        sal_mutex_destroy(p_usw_eunit_master[lchip]->mutex);
    }

    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->init_deinit)
    {
        MCHIP_EUNIT(lchip)->init_deinit(lchip, 1);
    }

    mem_free(p_usw_eunit_master[lchip]);
    if (DRV_FROM_AT(lchip))
    {
        uint8 i = 0;
        /*sys_emsg_deinit(lchip);*/
        for ( i = SYS_PP_BASE(lchip) + 1; i < SYS_PP_BASE(lchip) + SYS_PP_NUM(lchip); i++)
        {
            p_usw_eunit_master[i] = NULL;
        }
    }
    return CTC_E_NONE;
}

int32
sys_usw_eunit_init(uint8 lchip)
{
    uint8 i = 0;
    int32 ret = CTC_E_NONE;

    if (!DRV_FROM_TMM(lchip))
    {
        return CTC_E_NONE;
    }
    if (lchip != SYS_PP_BASE(lchip))
    {
        return CTC_E_NONE;
    }
#if (SDK_WORK_PLATFORM == 1 || SDB_MEM_MODEL == SDB_MODE) && !defined EUNIT_SIM
    return ret;
#endif
#define EUNIT_FEATURE_CHK(...) MCHIP_FEATURE_CAP(__VA_ARGS__)

    if (FALSE == EUNIT_FEATURE_CHK(lchip, CTC_FEATURE_DTEL)
        && FALSE == EUNIT_FEATURE_CHK(lchip, CTC_FEATURE_SC_OAM)
        && FALSE == EUNIT_FEATURE_CHK(lchip, CTC_FEATURE_NPM)
        && FALSE == EUNIT_FEATURE_CHK(lchip, CTC_FEATURE_PTP))
    {
        /*Dont Need Init*/
        return CTC_E_NONE;
    }

    LCHIP_CHECK(lchip);
    if (p_usw_eunit_master[lchip])
    {
        return CTC_E_NONE;
    }
    MALLOC_ZERO(MEM_SYSTEM_MODULE, p_usw_eunit_master[lchip], sizeof(sys_usw_eunit_master_t));
    if (NULL == p_usw_eunit_master[lchip])
    {
        return CTC_E_NO_MEMORY;
    }
    sal_mutex_create(&p_usw_eunit_master[lchip]->mutex);
    if (NULL == p_usw_eunit_master[lchip]->mutex)
    {
        ret = CTC_E_NO_MEMORY;
        goto error_return;
    }
    p_usw_eunit_master[lchip]->isr = g_eunit_isr;
    sys_usw_eunit_regitser_isr(lchip, SYS_EUNIT_ISR_ERROR, _sys_usw_eunit_error_isr_func);

    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->init_deinit)
    {
        CTC_ERROR_GOTO(MCHIP_EUNIT(lchip)->init_deinit(lchip, 0), ret, error_return);
    }

    /*if (DRV_FROM_AT(lchip))
    {
        CTC_ERROR_GOTO(sys_emsg_init(lchip), ret, error_return);
    }*/

    /*warmboot reloading do not need do EUNIT reset*/
    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->reset && 
        !((CTC_WB_ENABLE(lchip) && CTC_WB_STATUS(lchip) == CTC_WB_STATUS_RELOADING)))
    {
        ctc_eunit_install_t eunit;
        sal_memset(&eunit, 0, sizeof(ctc_eunit_install_t));
        if (DRV_IS_AT(lchip))
        {
#if (SDK_WORK_PLATFORM == 0)
            MCHIP_EUNIT(lchip)->reset(lchip, 0, &eunit);
            MCHIP_EUNIT(lchip)->reset(lchip, 1, &eunit);
            if (SYS_VCHIP_DUAL_CORE_MODE(lchip))
            {
                MCHIP_EUNIT(lchip)->reset(lchip, 4, &eunit);
            }
#endif
        }
        if ((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)))
        {
            MCHIP_EUNIT(lchip)->reset(lchip, SYS_EUNIT_S, &eunit);
            MCHIP_EUNIT(lchip)->reset(lchip, SYS_EUNIT_M, &eunit);
        }
    }
    if (DRV_FROM_AT(lchip))
    {
        for ( i = SYS_PP_BASE(lchip) + 1; i < SYS_PP_BASE(lchip) + SYS_PP_NUM(lchip); i++)
        {
            p_usw_eunit_master[i] = p_usw_eunit_master[SYS_PP_BASE(lchip)];
        }
    }

    drv_usw_register_eunit_lock(lchip, sys_usw_eunit_lock_cb);
    SYS_CB_REGISTER(lchip, SYS_CB_EUNIT_SET_CFG, sys_usw_eunit_set_cfg);
    SYS_CB_REGISTER(lchip, SYS_CB_EUNIT_GET_CFG, sys_usw_eunit_get_cfg);

    return CTC_E_NONE;

error_return:
    sys_usw_eunit_deinit(lchip);

    return ret;
}

#endif

